<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
	
	//require_once("ILoader.php");

    class DBUtil
    {
        public static function validateCriteria($criteria)
        {
            if(trim($criteria) !== "")
                return " ".$criteria;
            return "";
        }
    }
	
	class DeliveryOrder extends AbstractNode
	{
		public $ID = 0;
        public $DONum = "";
        public $CustCode = "";
		public $Distance = 0;
		public $Weight = 0;
		public $Volume = 0;
		public $Delivered = false;
        public $CarGroupID = 0;
		
		public function __construct($ID, $DONum, $custCode, $weight, $volume, $longitude, $latitude)
		{
			$this->ID = $ID;
            $this->DONum = $DONum;
            $this->CustCode = $custCode;
			$this->Weight = $weight;
			$this->Volume = $volume;
			$this->longitude = $longitude;
			$this->latitude = $latitude;
		}
		
		public function toString()
		{
			$str = "{";
			
			foreach($this as $key => $val)
			{
				if($key === "Delivered")
					$str .= $key." : ".($this->Delivered?"true":"false").", ";
				else
					$str .= $key." : '".$val."', ";
			}
			$str = trim($str, ", ");
			
			$str .= "}";
			return $str;
		}

        public function insert($db)
        {
            $db->query("INSERT INTO deliveryorder ".
                "(DONum, CustCode, Distance, Weight, Volume, Delivered, longitude, latitude) ".
                " VALUES (".
                "'" . $this->DONum . "', " .
                "'" . $this->CustCode . "', " .
                "'" . $this->Distance . "', " .
                "'" . $this->Weight . "', " .
                "'" . $this->Volume . "', " .
                "" . ($this->Delivered?1:0) . ", " .
                "'" . $this->getLongitude() . "', " .
                "'" . $this->getLatitude() . "')"
            );
            $result = $db->query("SELECT LAST_INSERT_ID() AS ID")->result();

            $this->ID = $result[0]->ID;
        }

        private function update($db)
        {
            $db->query("UPDATE deliveryorder SET ".
            "DONum = '".$this->DONum."', ".
            "CustCode = '".$this->CustCode."', ".
            "Distance = '".$this->Distance."' ".
            "Weight = '".$this->Weight."', ".
            "Volume = '".$this->Volume."', ".
            "Delivered = ".($this->Delivered?1:0).", ".
            "longitude = '".$this->getLongitude()."', ".
            "latitude = '".$this->getLatitude()."' ".
            "WHERE ID = '".$this->ID."'");
        }

        public function save($db)
        {
            if(sizeof(self::fetch($db, "WHERE ID = '".$this->ID."'")) === 0)
                $this->insert($db);
            else
                $this->update($db);
        }

        public static function delete($db, $criteria = "")
        {
            $criteria = DBUtil::validateCriteria($criteria);
            $db->query("DELETE FROM deliveryorder".$criteria);
        }

        public static function fetch($db, $criteria = "")
        {
            $criteria = DBUtil::validateCriteria($criteria);
            $result = $db->query("SELECT * FROM deliveryorder".$criteria)->result();

            $doList = array();
            foreach($result as $key => $val)
            {
                $do = new DeliveryOrder($val->ID, $val->DONum, $val->CustCode, $val->Weight, $val->Volume, $val->longitude, $val->latitude);
                $do->Distance = $val->Distance;
                $do->Delivered = ($val->Delivered === 1?true:false);
                $do->CarGroupID = $val->CarGroupID;
                $doList[] = $do;
            }
            return $doList;
        }
	}
	
	class CarGroup extends AbstractNode
	{
		public $CarID = "";
		/*public function getCarID()
		{
			$carID = $this->CarID;
			if(sizeof($this->Path) > 0)
			{
				$carID .= "(".$this->Path[sizeof($this->Path) - 1]->ID.")";
			}
			return $carID;
		}*/
		
		public $MaxDistance = 0;
		public $MaxWeight = 0;
		public $MaxVolume = 0;
		
		public $Weight = 0;
		public $Volume = 0;
		public $Path = null;
		
		public function __construct($carID, $maxDistance, $maxWeight, $maxVolume)
		{
			$this->CarID = $carID;
			$this->MaxDistance = $maxDistance;
			$this->MaxWeight = $maxWeight;
			$this->MaxVolume = $maxVolume;
			$this->Path = array();
		}
		
		public function deliver(DeliveryOrder $do)
		{
            $d = AbstractNode::getDistance($this, $do);
			$w = intval($this->Weight) + intval($do->Weight);
			$v = intval($this->Volume) + intval($do->Volume);

			if($d > $this->MaxDistance || $w > $this->MaxWeight || $v > $this->MaxVolume)
			{
				//echo "<br />Car : ".$this->getCarID()."(".$this->MaxWeight.", ".$this->MaxVolume.")"." to ".$do->ID."(".$w.", ".$v.")"."<br />";
				return false;
			}
			else 
			{
				$this->setLongitude($do->getLongitude());
				$this->setLatitude($do->getLatitude());
			    $this->Weight = $w;
                $this->Volume = $v;
				$this->Path[] = $do;
			    return true;
            }
		}

        public function deliverDO(DeliveryOrder $do)
        {
            $w = intval($this->Weight) + intval($do->Weight);
            $v = intval($this->Volume) + intval($do->Volume);
            $this->setLongitude($do->getLongitude());
            $this->setLatitude($do->getLatitude());
            $this->Weight = $w;
            $this->Volume = $v;
            $this->Path[] = $do;
        }

        public function isValid(DeliveryOrder $do)
        {
            $d = AbstractNode::getDistance($this, $do);
            $w = intval($this->Weight) + intval($do->Weight);
            $v = intval($this->Volume) + intval($do->Volume);

            if($d > $this->MaxDistance || $w > $this->MaxWeight || $v > $this->MaxVolume && !$this->isDelivered($do))
            {
                //echo "<br />Car : ".$this->getCarID()."(".$this->MaxWeight.", ".$this->MaxVolume.")"." to ".$do->ID."(".$w.", ".$v.")"."<br />";
                return false;
            }
            else
            {
                return true;
            }
        }
		
		public function isDelivered(DeliveryOrder $do)
		{
			foreach($this->Path as $key => $val)
			{
				if($val->ID === $do->ID) return true;
			}
			
			return false;
		}
		
		public function cloneObject()
		{
			$car = new CarGroup($this->CarID, $this->MaxDistance, $this->MaxWeight, $this->MaxVolume);
			$car->Weight = $this->Weight;
			$car->Volume = $this->Volume;
			$car->Path = $this->Path;
			$car->setLongitude($this->getLongitude());
			$car->setLatitude($this->getLatitude());
			return $car;
		}

        private function insert($db)
        {
            $db->query("INSERT INTO cargroup ".
                "(MaxDistance, MaxWeight, MaxVolume) ".
                " VALUES (".
                "'" . $this->MaxDistance . "', " .
                "'" . $this->MaxWeight . "', " .
                "'" . $this->MaxVolume . "')"
            );
            $result = $db->query("SELECT LAST_INSERT_ID() AS ID")->result();

            $this->CarID = $result[0]->ID;
        }

        private function update($db)
        {
            $db->query("UPDATE cargroup SET ".
                "MaxDistance = '".$this->MaxDistance."', ".
                "MaxWeight = '".$this->MaxWeight."', ".
                "MaxVolume = '".$this->MaxVolume."' ".
                "WHERE CarGroupID = '".$this->CarID."'");
        }

        public function save($db)
        {
            if(sizeof(self::fetch($db, "WHERE CarGroupID = '".$this->CarID."'")) === 0)
                $this->insert($db);
            else
                $this->update($db);
        }

        public static function delete($db, $criteria = "")
        {
            $criteria = DBUtil::validateCriteria($criteria);
            $db->query("DELETE FROM cargroup".$criteria);
        }

        public static function fetch($db, $criteria = "")
        {
            $criteria = DBUtil::validateCriteria($criteria);
            $result = $db->query("SELECT * FROM cargroup".$criteria)->result();

            $cgList = array();
            foreach($result as $key => $val)
            {
                $cg = new CarGroup($val->CarGroupID, $val->MaxDistance, $val->MaxWeight, $val->MaxVolume);
                $cgList[] = $cg;
            }

            return $cgList;
        }
		
		public function toString()
		{
			$path = "";
			if($this->Path === NULL)
				$path = "null";
			else 
			{
				$path = "[";
				
				foreach($this->Path as $index => $do)
				{
					$path .= $do->toString().", ";
				}
				$path = trim($path, ", ");
				
				$path .= "]";
			}
			
			$str = "{";
			
			foreach($this as $key => $val)
			{
				if($key === "Path")
					$str .= $key." : ". $path.", ";
				else
					$str .= $key." : '".$val."', ";
			}
			$str = trim($str, ", ");

			$str .= "}";
			return $str;
		}
	}

    class CarGroupView
    {
        public $CarGroupID = 0;
        public $MaxDistance = 0;
        public $MaxWeight = 0;
        public $MaxVolume = 0;
        public $ID = 0;
        public $DONum = "";
        public $CustCode = "";
        public $Distance = 0;
        public $Weight = 0;
        public $Volume = 0;
        public $Delivered = false;
        public $longitude = 0;
        public $latitude = 0;

        public static function fetch($db, $criteria = "")
        {
            $criteria = DBUtil::validateCriteria($criteria);
            $result = $db->query(
                "SELECT * FROM cargroup cg
                INNER JOIN deliveryorder do ON do.CarGroupID = cg.CarGroupID".$criteria)->result();

            $cgvList = array();
            foreach($result as $key => $val)
            {
                $cgv = new CarGroupView();
                $cgv->MaxDistance = $val->MaxDistance;
                $cgv->MaxWeight = $val->MaxWeight;
                $cgv->MaxVolume = $val->MaxVolume;
                $cgv->ID = $val->ID;
                $cgv->DONum = $val->DONum;
                $cgv->CustCode = $val->CustCode;
                $cgv->Distance = $val->Distance;
                $cgv->Weight = $val->Weight;
                $cgv->Volume = $val->Volume;
                $cgv->Delivered = $val->Delivered;
                $cgv->longitude = $val->longitude;
                $cgv->latitude = $val->latitude;

                $cgvList[] = $cgv;
            }

            return $cgvList;
        }

        public function toString()
        {
            return json_encode($this);
        }
    }

?>